核心概念
    Entry
    // 指示以哪个文件为入口起点开始打包
        /*
            1.string --> './src/'
              单入口
              打包形成一个chunk，输出一个bundle文件
              此时chunk默认名称是 main.js
            2.arry --> 
              多入口
              所有入口文件都只形成一个bundle
              --> 在HMR中让html热更新生效
            3.object --> {
                index: './src',
                
             }
              多入口
              有几个入口文件就形成几个chunk 输出几个bundle
              此时chunk名称  是 key

            4.特色用法 {
                index: ['./src', './sss/'], // 打包在一起
                add: './ '
            }
        */
    Output
    // 输出指示打包后的资源输出到哪里去
        module.exports = {
            output: {
                // 指定名称+目录
                filename: 'js/[name].js',
                // 资源输出的公共目录
                path: resolve(__dirname, 'build'),
                // 所有资源引入公共路径的前缀--> img/a.jpg--> /img/a.jpg
                pubilcPath: ('/'),
                // 非入口chunk 名称
                chunkFilename: '[name]_chunk.js',
                // 整个库向外暴露的变量名 外面可以直接引入使用
                library :'[]' ,
                // 变量名添加到哪个上
                libraryTarget: 'window'
            }
        }
    Loader
    // 让webpack能够去处理那些非js文件（webpack自身只能理解js）
        module.exports = {
            module: {
                rules: [
                    {
                        test: '',
                        // 多个loader用ues
                        ues:['style-loader', 'css-loader']
                    },
                    {
                        test: '',
                        // 排除 node_modules下的js文件
                        exclude: /node_modules/,
                        // 只检测src下的内容
                        include: resolve(__dirname, 'src'),
                        // 优先执行
                        enfore: 'pre', // 'post' 延后执行
                        // 单个个loader
                        loader:'style-loader',

                    },
                    {   
                        // 以下只会生效一个
                        oneof :[]
                    }
                ]
            }
        }
    plugins
    // 插件
    // 用于执行范围更广的任务，插件的范围包括从打包优化和压缩，一直到从新定义环境中的变量等
    Mode
    //模式  自动启用插件
    // development开发模式 能让代码本地调试运行的环境  css整合到js中
    // production生产模式  能让代码优化上线运行的环境
  其他概念
        module.exports = {
            mode: 'develpoment',
            // 解析模块
            resolve: {
                // 配置解析模块路径别名 优点简化路径 缺点路径没有提示
                alias: {
                    $css: resolve(__dirname, 'src/css')
                },
                // 配置省略文件路径后缀名
                extensions: ['.js', '.json', '.css'],
                // 告诉 webpack 解析模块失去找哪个目录
                modules: ['node_modules']
            },
            // 生产环境
            devServer: {
                // 运行代码的目录 
                contentBase: resolve(__dirname, 'build'),
                // 监视contentBase 目录下的所有文件 一旦变化就会 从新打包从新刷新浏览器
                watchContentBase: true,
                watchOptions: {
                    // 监视忽略文件
                    ignored: /node_modules/ 
                },
                // 启动gizp压缩
                compress: true,
                // 端口号
                port: 5000,
                // 域名
                host: 'localhost',
                // 自动打开浏览器
                open: true,
                // 开启HMR功能
                hot: true,
                // 不需要显示启动服务器日志信息
                clientLogLevel: 'none',
                // 除了一些基本启动信息以外，其他内容都不要显示
                quiet: true,
                // 如果出现错误不要全屏提升
                overlay: false,
                // 服务器代理 --> 解决开发环境跨域问题
                proxy: {
                    // 一旦devServer(5000)受到 /api/xxx 的请求 就会把请求转发给另外一个服务器
                    'api' :{
                        target: 'http://localhost:3000',
                        // 发生请求时 请求路径重写 /api/xxx --> /xxx (去掉/api)
                        pathRewrite: {
                            '^api' : ''
                        }
                    }
                }
            }
        }

运行指令
    将ES6模块化编译成浏览器能够识别的模块
      开发环境
        // webpack ./src/index.js -o ./build/build.js --mode=development
        // weback会以./src/index.js为文件入口开始 -o 打包输出到 ./build/.build.js  整体打包环境是开发环境
      生产环境  
        // webpack ./src/index.js -o ./build/build.js --mode=production
      /* html页面引用打包后的资源
         只能处理js/json资源,不能处理css/img
         生产环境比开发环境多一个压缩js代码 */

    打包样式资源css/img
        webpack配置文件webpack.config.js 
        // 指示webpack 干哪些活 当你运行webpack 指令时会加载里面的配置
        // 下载webpack loader包  npm i css-loader style-loader -D
        const {resolve} = require('path');
        module.exports = {
            // webpack配置
                // 入口起点
                    entry:'./src/',
                // 输出
                    output: {
                        // 输出文件名
                        filename: 'built.js',
                        // 输出路径
                        // __dirname 当前文件的绝对路径node.js
                        path: resolve(__dirname, 'build'),
                    },
                // loader的配置
                    module: {
                        rules: [
                            // 详细的loader配置
                            // 不同的文件必须配置不同的loader处理
                            { 
                                // 匹配哪些文件
                                test: /\.css$/,
                                // 使用哪些loader进行处理
                                use: [
                                    // use数组中loader执行顺序是从下到上
                                    // 创建style标签，将js中的样式资源插入进行，添加到head中生效
                                    'style-loader',
                                    // 将css文件变成common.js模块加载js中，里面是样式字符串
                                    'css-loader',
                                    // less 文件编译成css文件 需要下两个包 Less 和less-loader
                                    'less-loader'
                                ]
                            }
                            
                        ]
                    },
                // plugins 的配置
                    plugins: [
                        // 详细
                    ],
                //模式
                    mode: 'development',
            }
            
    打包html资源
    // loader  1 下载 2 使用（配置loader）
    // plugins 1.下载 npm i html-webpack-plugins -D 2.引入 3 使用
        const {resolve} = require('path');
        // 引入
        const HtmlWebpackPlugin = require('html-webpack-plugin');
        module.exports = {
            entry: './',
            output: {
                filename: 'built.js',
                path: resolve(__dirname, 'build')
            },
            module: {
                rules: [
                    // loader 配置
                ]
            },
            plugins: [     
                // 默认会创建一个空的HTML 自动引入打包输出的所有资源(js/css)
                new htmlWebpackPlugins(
                     // 需要有结构的HTML文件
                    {   // 复制文件 并自动引入打包输出的所有资源(js/css)
                        template: './'
                    })
            ],
            mode: 'development'
        }        
    
    打包图片资源
        const {resolve} = require('path');
        const HtmlWebpackPlugin = require('html-webpack-plugin')
        module.exports = {
            entry: '',
            output: {
                filename: '',
                path: resolve(__dirname, 'build')
            },
            module: {
                rules: [
                    {
                        text: /\.less$/,
                        use: [
                            'style-loader',
                            'css-loader',
                            'less-loader'
                        ]
                    },
                    // 图片处理
                    {   // 处理不了html的图片
                        test: /\.(jpg|png|gif)$/,  
                        // 下载两个包 url-loader file-loader
                        loader: 'url-loader',
                        options: {
                            // 图片大小小于8kb 就会被base64处理
                            // 优点减少请求数量  缺点图片体积更大
                            limit: 8 * 1024,
                            // 问题 因为url-loader默认使用es6模块解析 HTML-loader引入图片是commonjs
                            // 解析时会出现问题[object module]
                            // 解决 关闭url-loader的es6模块使用commonjs解析
                            esModule: false,
                            // 给图片进行从命名
                            // [hash:10] 取图片的hash的前10位
                            // [ext] 取原来文件的扩展名
                            name: '[hash:10].[ext]'
                        }
                    },
                    {
                        test: /\.html$/,
                        // 处理HTML文件的img图片（复制引入img从而能被url-loader处理）
                        loader: 'html-loader'
                    }
                ]
            },
            plugins: [
                new HtmlWebpackPlugin({
                    template: './'
                })
            ],
            mode: 'development',
        }
    
    打包其他资源
        // 字体图标之类的
        const {resolve} = require('path');
        const HtmlWebpackPlugin = require ('html-webpack-plugin')
        module.exports = {
            entry:'',
            output: {
                filename:'',
                path: resolve(__dirname, 'build')
            },
            module: {
                rules: [
                    {
                       test: /\.css$/,
                       use:[
                           'style-loader',
                           'css-loader'
                       ], 
                    },
                    // 打包其他资源 除了（html/css/js/）以外的资源
                    {   
                        // 排除资源
                        exclude: /\.(css|js|html)$/,
                        loader: 'file-loader',
                        options: {
                            name: '[hash:10].[ext]',
                        }
                    }
                ]
            },
            plugins: [
                new HtmlWebpackPlugin({
                    template: './'
                })
            ],
            mode: 'development',
        }
    
    devServer
    // 开发服务器  自动化自动编译自动打开浏览器自动刷新浏览器
       module.export = {
           entry: '',
           output: {
               filename: '',
               path:resolve(__dirname, ' '),
           },
           module: {
           },
           plugins: {},
           mode: 'development',
           // deServer
           // 特点 只会在内存中编译打包  不会有任何输出
           // 启动指令为  npx webpack-dev-server   下载 npm i webpack-dev-server -D
           devServer: {
               contentBase: resolve(__dirname, 'build'),
               // 启动gzip压缩
               compress: true,
               // 端口号
               port: 3000,
               // 自动打开浏览器
               open: true,
           }
       }

开发环境的搭建
    /*  能让代码运行即可
        项目运行指令 
            webpack  会将打包结果输出出去
            npx webpack-dev-server 只会在内存中编译打包， 没有输出
    */ 
     

    const {resolve} = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plgin');
    module.exports = {
        entry: './',
        output: {
            filename: './',
            path: resolve(__dirname, 'build'),
        },
        module: {
            rules: [
                // loader
                {   //处理less
                    test: /\.less$/,
                    use: [
                        'style-loader',
                        'css-loader',
                        'less-loader'
                    ]
                },
                {   // 处理CSS
                    test: /\.css$/,
                    use: [
                        'style-loader',
                        'css-loader'
                    ]
                },
                {   //  处理图片
                    test: /\.(png|ipg|gif)$/,
                    loader: 'url-loader',
                    options: {
                        limit: 8*1024,
                        name: '[hash: 10].[ext]',
                        esModule: false,
                        outputPath: 'imgs'
                    }
                },
                {   //  处理html中img文件
                    test: /\.html$/,
                    loader: 'html-loader'
                },
                {   //  其他资源
                    exclude: /\.(html|js|css|less|jpg|png|gif)/,
                    loader: 'file-loader',
                    options: {
                        name: '[hash: 10].[ext]',
                        outputPath: 'media'
                    }
                }
            ]
        },
        plugins: [
            // 处理HTML
            new HtmlWebpackPlugin({
                template: './'
            })
        ],
        mode: 'development',
        // 自动打包
        devServer: {
            contentBase: resolve(__dirname, 'build'),
            port: 3000,
            open: true,
        }
    };

生产环境
    提取css成单独文件
    //  使用插件  npm-css-extract-plugin -D 
    CSS兼容性处理
    // CSS兼容性处理: postcss -->postcss-loader postcss-preset-env
    压缩CSS
    // optimize-css-assets-webpack-plugin -D
    const MiniCssExtractPlugin = require ('mini-extract-plugin');
    const OptimizeCssAssetWebpackPlugin = require(' optimize-css-assets-webpack-plugin')
    module.exports = {
        entry: '',
        output: {
            filename:'',
            path: resolve(__dirname, ' ')
        },
        module: {
            rules: [
                {
                    test: /\.css$/,
                    use: [
                        // 创建style 标签将样式放入
                        // 'style-loader',
                        // 这个loader取代style-loader 提取js中的css成单独文件
                        MiniCssExtractPlugin.loader,
                        // 将css文件整合到JS文件中
                        'css-loader',
                       
                        {   // CSS兼容性处理
                            // 帮postcss找到package.json中browserslist里面的配置，通过配置加载指定的css兼容性样式
                                /*  
                                    默认情况下为生产环境 与mode无关
                                    开发环境设置node环境变量
                                        process.env.NODE_ENV = development

                                    "browserslist": {
                                        "development":[
                                            "last 1 chrome version",
                                            "last 1 firefox version",
                                            "last 1 safari version"
                                        ],
                                        "production": [
                                            ">0.2%",
                                            "not dead",
                                            "not op_mini all"
                                        ]
                                    }
                                 */
                            loader: 'postcss-loader',
                            options: {
                                ident: 'postcss',
                                plugins: () => [
                                    // postcss 的插件
                                    require('potcss-preset-env')()
                                ]
                            }
                        }
                    ]
                }
            ]
        },
        plugins: [
            new HtmlWebpackPlugin({
                template: './',
            }),
            // 提取CSS的插件
            new MiniCssExtractPlugin({
                // 输出文件重命名
                filename: './'
            }),
            // 压缩css的插件
            new OptimizeCssAssetWebpackPlugin()
        ]
    }

    js的语法检查
    module.exports = {
        module: {
            rules:[
                /*  语法检查 eslint-loader eslint 下载两个包
                    只检查用户自己的源代码， 第三方库不检测
                    设置检测规则： 
                        package.json中eslintCinfig中设置
                            "eslintConfig": {
                                "extends": "airbnb-base"
                            }
                        airbnb --> eslint-config-airbnb-base  eslint eslint-plugin-import 下载三个包
                */
                {
                    test: /\.js$/,
                    exclude: /node_modules/,
                    loader: 'eslint-loader',
                    options: {
                        fix: true, // 自动修复eslint的错误
                    }
                }
            ]
        }
    }

    js的兼容性处理
    module.exports = {
        module: {
            rules:[
               /*
                  js兼容性处理： babel-loader @babel/preset-env @babel/core
                    1.基本js兼容性处理-->@babel/preset-env
                        问题： 只能转换基本语法，如promise高级语法不能转换

                    2.全部js兼容性处理-->@babel/polyfill
                        通过import''在js源代码中引入即可
                        问题 ： 将所有兼容性代码全部引入 体积太大

                    3.需要做兼容性处理的就做 --> corejs
                      较高级的兼容性处理， 结合1 用
               */
              {   
                  test: /\.js$/,
                  exclude: /node_modules/,
                  loader: 'babel-loader',
                  options: {
                      // 预设：指示Babel做哪些兼容性处理
                      presets: 
                        [
                          '@babel/preset-env',
                          { 
                            // 按需加载
                            useBuiltIns: 'usage',
                            // 指定corejs版本
                            corejs: {
                                version: 3
                            },
                            // 指定兼容性做到哪个版本的浏览器
                            targets: {
                                chrome: '60',
                                firefox: '60',
                                ie: '9',
                                safari: '10',
                                edge: '17'
                            }
                          }
                        ]
                    }
                }
            ]
        }
    }

    js压缩
    // 生产环境下会自动压缩js代码

    html压缩
        module.exports = {
            entry: './',
            output: {
                filename: 'built.js',
                path: resolve(__dirname, 'build')
            },
            module: {
                rules: [
                ]
            },
            plugins: [     
                new htmlWebpackPlugins(
                    {  
                        template: './',
                        // 压缩html
                        minify: {
                            // 移除空格
                            collapseWhitespace: true,
                            // 移除注释
                            removeComments: true
                        }
                    })
            ],
            mode: 'development'
        }        
    
    生产环境配置
        const {resolve} = require('path');
        const MiniCssExtractPlugin = require('mini-css-extract-plugin');
        const OptimizeCssAssetWebpackPlugin = require('optimize-css-assets-webpack-plugin');
        const HtmlWebpackPlugin = require ('html-webpack-plugin');
const { map } = require('jquery')

        // 定义nodejs的环境变量， 决定使用browserslist的哪个环境
        process.env.NODE_ENV = 'production'
        const commonCssLoader = [
            MiniCssExtractPlugin.loader,
            'css-loader',
            {   // 还需再package.json中定义browserslist
                loader: 'postcss-loader',
                options: {
                ident: 'postcss',
                plugins: () => [
                    require('postcss-preset-env')()
                        ]
                }
            }
        ]
        module.exports = {
            entry: './',
            output: {
                filename: './',
                path: resolve(__dirname, 'build')
            },
            module: {
                rules:[
                    {   
                        // css提取
                        test: /\.css$/,
                        use: [...commonCssLoader]
                    },
                    {   
                        // less提取
                        test: /\.less$/,
                        use: [...commonCssLoader,'less-loader']
                    },
                    // 当一个文件要被多个loader处理，那么一定要指定loader的执行先后顺序
                    {   
                        // js代码错误修复
                        // 在package.json中eslintConfig --> airbnb
                        test: /\.js$/,
                        exclude: /node_modules/,
                        // loader 优先执行
                        enforce: 'pre',
                        loader: 'eslint-loader',
                        options: {
                            fix: true,
                        }
                    },
                    {
                        // js兼容性
                        test: /\.js$/,
                        exclude: /node_modules/,
                        loader: 'babel-loader',
                        options: {
                            presets: [
                                '@babel/preset-env',
                                {
                                    useBuiltIns: 'usage',
                                    corejs: {
                                        version: 3
                                    },
                                    targets: {
                                        chrome: '60',
                                        firefox: '50'
                                    }
                                }
                            ]
                        }
                    },
                    {   
                        // 图片资源处理
                        test: /\.(jpg|png|gif)/,
                        loader: 'url-loader',
                        options: {
                            limit: 8 * 1024,
                            name: '[hash:10].[ext]',
                            outputPath: 'imgs',
                            esModule: false
                        }
                    },
                    {   
                        // html 处理
                        test: /\.html$/,
                        loader: 'html-loader'
                    },
                    {   
                        // 其他资源处理
                        exclude: /\.(js|css|less|html|jpg|png|gif)/,
                        loader: 'file-loader',
                        options: {
                            outputPath: 'media'
                        }
                    }
                ]
            },
            plugins: [
                new MiniCssExtractPlugin({
                    filename: 'css/',
                }),
                new OptimizeCssAssetWebpackPlugin(),
                new HtmlWebpackPlugin({
                    template: './',
                    minify: {
                        collapseWhitespace: ture,
                        removeComments: true
                    }
                })
            ],
            mode: 'production'
        }

性能优化配置
    开发环境性能优化
        // 优化打包构建速度
        // 优化代码调试功能

        HMR功能 
        // 热模块替换 一个模块变化只会从新打包这一个模块

        /* 
            样式文件：可以使用HMR功能，style-loader内部实现了
            js文件，html文件 默认不使用hmr
                js解决： 添加支持HMR功能的代码
                    注意：HMR功能对js的处理只能处理  非入口js的文件

                  写在入口文件内
                    if(module.hot) {
                        module.hot.accept('./print.js', function(){
                            // 方法会监听 print.js文件的变化 一旦发生变化， 其他模块不会从新打包构建
                            // 会执行之后的监听函数
                        })
                    }
                html解决： 修改entry入口 将html文件引入(但是不用做hmr)

        */
            module.exports = {

                devServer: {
                    contentBase: resolve(__dirname, 'build'),
                    port: 3000,
                    open: true,
                    // 热模块替换
                    hot: true,
                }
            };
            // 更改后重启webpack

        source-map
        // 提供源代码到构建后代码映射的技术（如果构建后代码出错了，可以通过映射追踪源代码错误）
            module.exports = {
                devtool: 'source-map'
                /*
                    source-map 外部 
                        错误代码准确信息 和源代码的错误位置

                    inline-source-map 内联  
                        只生成一个内联source-map
                        错误代码准确信息 和源代码的错误位置

                    hidden-source-map 外部
                        错误代码准确信息 没有错误 信息
                        不能追踪代码错误，只能提示到构建后代码的错误位置

                    eval-source-map  内联
                        每一个文件都生成对应的source-map 都在eval
                        错误代码准确信息 和源代码的错误位置

                    nosources-source-map 外部
                        错误代码准确信息 没有任何源代码的错误

                    cheap-source-map 外部
                        错误代码准确信息 和源代码的错误位置
                        只精确到行

                    cheap-module-source-map 外部
                        错误代码准确信息 和源代码的错误位置

                  外部生成了文件，内联没有，内联构建速度更快 体积更大

                    开发环境：速度快，调试更友好
                        速度快： eval>inline>cheap>
                        调试更友好 source-map cheap-module-source-map cheap-source-map
                        --> eval-source-map

                    生产环境：要不要隐藏，调试要不要友好
                        生产模式不用内联
                        --> source-map

                */ 
            }

    生产环境性能优化
        // 优化打包速度
        // 缓存 
            module.exports = {
                module: {
                    rules: [
                        {
                            // 处理相同的放此处  
                                // 在package.json中eslintConfig --> airbnb
                                test: /\.js$/,
                                exclude: /node_modules/,
                                // loader 优先执行
                                enforce: 'pre',
                                loader: 'eslint-loader',
                                options: {
                                    fix: true,
                                    // 开启bable缓存
                                    // 第二次构建是会读取之前的缓存
                                    cacheDirectory: true,
                                }
                            
                        },
                        {   // 以下loader只会匹配一个
                            // 注意：不能有两个配置处理一个文件
                            oneOf: [
                                // 代码
                                {
                                    test: /\.js$/,
                                    exclude: /node_modules/,
                                    loader: 'babel-loader',
                                    options: {
                                        presets: [
                                            '@babel/preset-env',
                                            {
                                                useBuiltIns: 'usage',
                                                corejs: {
                                                    version: 3
                                                },
                                                targets: {
                                                    chrome: '60',
                                                    firefox: '50'
                                                }
                                            }
                                        ]
                                    }
                                },
                            ]
                        }
                    ]
                }
            }
        // 优化代码运行的性能
        缓存
            babel缓存
            // 第二次打包构建更快
            文件资源缓存
            // 代码上线运行缓存更好使用
                输出路径文件名使用哈希值缓存 // 浏览器刷新使用缓存
                // chunkhash 更具chunk生成的hash如果打包来源与一个chunk那么hash就一样
                    // js css 一样的hash值
                // contenthash 每个文件的hash都不一样 ./build[contenthash:10].js
    
        treeshaking
        // 去除应用程序中没有使用的代码
        /* 
            使用前提：必须使用ES6模块化  开启production模式

            在package.json 中
                "sideEffects": false 所有代码都没有副作用（都可以进行tree shaking）
                问题 可能会把css/@babel/polfill
                "sideEffects": ["*.css", "*.less" ] 不会被处理
        */    

        codesplit
        // 代码分割 一个文件分割为3个文件实现并行加载 或者按需加载
        // 一般是单入口加 2.3一起用
          // 1多入口配置
            module.exports = {
                entry: {
                    // 多入口 有一个入口最终输出就有一个Bundle
                    main: './src/index.js',
                    test: './src/test.js'
                },
                output: {
                    // name 与上面 main test匹配
                    filename: 'js/[name].[contenthash:10].js'
                }
            }
          // 2
            module.exports = {
                entry: './src/index.js',
                output: {
                    filename: 'js/buil.[contenthash:10].js'
                },
                plugins: [],
                mode: 'production',
                // 单入口  可以将node_modules 中代码单独打包成一个chunk最终输出
                // 多入口时  自动分析多入口chunk中有没有公共的文件，如果有就会单独打包成一个chunk
                optimization: {
                   splitChunks:
                    { 
                       chunks: 'all'
                    }
                }
            }
            // 3 improt动态导入语法
            // 通过js代码让某个文件单独打包
            import(/* webpackChunkName: 'test' */'./') // 通过注释给打包名字命名
                .then(({mul, count}) => {
                    // 文件加载成功
                })
                .catch(() => {
                    // 文件加载失败
                })

    
        懒加载和预加载
            // js代码懒加载  文件需要使用时才加载
            document.querySelector('').onclick = function() {
                import(/* webpackChunkName: 'test', webpackPrefetch : true */'./').then(({mul}) => {
                // webpackPrefetch 预加载（慎用） 等其他资源加载完毕浏览器空闲了 再加载js文件
                })
            }
            
        PWA
          // 渐进式网络开发应用程序  离线可访问技术
          // work-webpack-plugin
          /*
            1.eslint不认识window navigator全局变量
                修改package.json中 eslintConfig
                "env": {
                    "browser": true  支持全局变量
             }
             2.sw代码必须运行再服务器上
                --> node.js
                --> 
                    npm i serve -g 
                    serve -s build 启动服务器将build 目录下所有资源暴露出去
          */
          const WorkWebpackPlugin = require('work-webpack-plugin');
          module.exports = {
            plugins: [
                new WorkWebpackPlugin({
                    //帮助serviceworker快速启动
                    clientsClaim: true,
                    // 删除旧的serviceworker
                    skipaWaiting: true
                    /* 
                        生成一个serviceworker文件
                       
                     index.js内注册： 
                            if('serviceWorker' in navigator) {
                                window.addEventListener('load',() => {
                                    navigator.serviceWorker.register('/service-worker.js)
                                    .then(() => {
                                        注册成功
                                    })
                                    .catch(() => {
                                        失败
                                    })
                                })
                            }
                        处理兼容性：
                    */
                })
            ]
          }
        
        多进程打包
            // npm i thread-loader -D
            module.exports = {
                module: {
                    rules: [
                        {
                                test: /\.js$/,
                                exclude: /node_modules/,
                                enforce: 'pre',
                                loader: 'eslint-loader',
                                options: {
                                    fix: true,
                                    cacheDirectory: true,
                                }
                            
                        },
                        {
                            oneOf: [
                                // 代码
                                {
                                    test: /\.js$/,
                                    exclude: /node_modules/,
                                    use: [
                                        // 开启多进程打包 只有工作消耗时间长才需要多进程打包 js使用
                                        {
                                            loader: 'thread-loader',
                                            options: {
                                                workers: 2 // 进程2个
                                            }
                                        },
                                        {
                                            loader: 'babel-loader',
                                            options: {
                                                presets: [
                                                    '@babel/preset-env',
                                                    {
                                                        useBuiltIns: 'usage',
                                                        corejs: {
                                                            version: 3
                                                        },
                                                        targets: {
                                                            chrome: '60',
                                                            firefox: '50'
                                                        }
                                                    }
                                                ]
                                            }
                                        }
                                    ]
                                },
                            ]
                        }
                    ]
                }
            }

        externals
        // 防止某一些包打包到最终输出的bundle中 彻底不打包
            module.exports = {
                entry: ' ',
                output: {

                },
                module: {},
                plugins: [],
                mode: 'production',
                externals: {
                    // 忽略库名 --npm包名
                    // 拒绝jquery被打包进来 忽略后html内需要手动引进
                    jquery: 'jQuery'
                }
            }

        DLL
        // 动态链接库 单独打包

        // webpack.dll.js 内写 对某些第三方库进行单独打包 （jQuery react vue ...） 运行一次
        // 运行指令为  webpack--config webpack.dll.js
        const {resolve} = require('path');
        const Webpack = require('webpack');
        module.exports = {
            entry: {
                // 最终打包生成的name--> jQuery
                //  ['jquery']--> 要打包的库是jQuery
                jquery: ['jquery']
            },
            output: {
                filename: '[name].js',
                path: resolve(__dirname, 'dll'),
                library: '[name]_[hash:10]' // 打包库向外暴露出去的内容叫什么名字
            },
            plugins: [
                // 打包生成一个 manifest.json文件 --> 提供一个jquery映射告诉jquery不需要打包
                new Webpack.DllPlugin ({
                    name: '[name]_[hash:10]', // 映射库的暴露内容名称
                    path: resolve(__dirname, 'dll/manifest.json'), // 输出文件路径
                })
            ]
        }
        // webpack.config.js内
        const webpack = require('webpack');
        const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
        module.exports = {
            plugins: [
                // 告诉webpack 哪些库不参与打包了，同时使用时的名称也得变
                new webpack.DllReferenvePlugin({
                    manifest: resolve(__dirname, 'dll/mainfest.json'), // 使用映射路径
                }),
                // 将某个文件打包出去去并在html中自动映入该资源
                new AddAssetHtmlWebpackPlugin({
                    filepath: resolve(__dirname, 'dll/jquery.js')
                })
            ]
        }
    
    优化环境配置